"""
/** Copyright 2020 Zhejiang Lab and Zhejiang University. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* =============================================================
*/
"""
from utils import logRequest
from visualization.models import AtlasCollection
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from rest_framework.decorators import api_view, permission_classes
from rest_framework.permissions import AllowAny
from django.db import IntegrityError, transaction
import datetime
from time import sleep
import tornado
import os
import json
import logging
import hashlib
from functools import partial
from urllib.parse import urljoin
from my_models.storage import ModelStorage

logger_name = 'visualization.views'
logger = logging.getLogger(logger_name)

class Metrics(APIView):
    @logRequest(logger_name)
    def get(self, request, format=None):
        metrics = AtlasCollection.objects.all()
        res = []
        for m in metrics:
            metric = {'id':m.id, 'name': m.atlas_uid, 'url':m.url, 'description':m.description}
            res.append(metric)
        return Response({'metrics' : res}, status=status.HTTP_200_OK)

    @logRequest(logger_name)
    @transaction.atomic
    def post(self, request):
        metric = AtlasCollection()
        metric_info = request.data["metric_info"]
        metric_info = json.loads(metric_info)
        metric.atlas_uid = metric_info.get('name', None)
        metric.description = metric_info.get('description', None)
        metric.file = request.data["file"]
        metric.md5 = get_md5(metric.file)
        if not metric.file:
            return Response(data="no file for upload", status=status.HTTP_400_BAD_REQUEST)
        try:
            metric.save()
            url = urljoin('file/', metric.file.name)
            metric.url = url
            metric.save()
        except Exception as e:
            return Response({'error': str(e)}, status=status.HTTP_400_BAD_REQUEST)
        return Response({'response': 'success'}, status=status.HTTP_201_CREATED)

    @logRequest(logger_name)
    def put(self, request):
        metric_info = request.data["metric_info"]
        metric_info = json.loads(metric_info)
        metric_id = metric_info["id"]
        metric = AtlasCollection.objects.filter(id=metric_id).first()
        metric.atlas_uid = metric_info.get('name', None)
        metric.description = metric_info.get('description', None)
        if request.data["file"] != 'null':
            # delete old json
            storage = ModelStorage()
            storage.delete(str(metric.file))
            metric.file = request.data["file"]
            metric.md5 = get_md5(metric.file)
        try:
            metric.save()
            url = urljoin('file/', metric.file.name)
            metric.url = url
            metric.save()
        except Exception as e:
            return Response(str(e), status=status.HTTP_400_BAD_REQUEST)
        return Response(data="success", status=status.HTTP_200_OK)

    def delete(self, request):
        metric_id = request.query_params.get('metric_id[]', None)
        metric = AtlasCollection.objects.filter(id=metric_id).first()
        # delete old json
        storage = ModelStorage()
        storage.delete(str(metric.file))
        try:
            metric.delete()
            return Response(data="success", status=status.HTTP_200_OK)
        except:
            return Response(data="error", status=status.HTTP_400_BAD_REQUEST)


        


class MetricNames(APIView):
    @logRequest(logger_name)
    def get(self, request, format=None):
        user = request.user
        graphs = AtlasCollection.objects.all()
        metric_names = [g.atlas_uid for g in graphs]
        return Response(metric_names, status=status.HTTP_200_OK)

class Graph(APIView):
    @logRequest(logger_name)
    def get(self, request, format=None):
        user = request.user
        metric_names = request.query_params.getlist('metric_names[]', [])
        logger.debug(metric_names)
        if len(metric_names) == 0:
            return Response({'error': 'Parameter errors'}, status=status.HTTP_400_BAD_REQUEST)
        graphs = AtlasCollection.objects.filter(atlas_uid__in=metric_names)
        logger.debug(graphs)
        res = {}
        for g in graphs:
            with open(g.url) as json_file:
                data = json.load(json_file)
            res.update(data)
        logger.debug('res')
        logger.debug(res.keys())
        return Response(res, status=status.HTTP_200_OK)

def get_md5(file, block_size=65536):
    md5 = hashlib.md5()
    for buf in iter(partial(file.read, block_size), b''):
        md5.update(buf)
    return md5.hexdigest()
